home *** CD-ROM | disk | FTP | other *** search
- Talkline - How it works.
- ~~~~~~~~~~~~~~~~~~~~~~~~
-
- Talkline is a sound of short duration, appended to the end of a message.
- In this fist version, up to 5 seconds of sound can be added.
- The purpose of this text file is to explain how the sound is coded
- and appended to the message. This first version is called version "A" and
- has the following characterization:
-
- 1-Sampling. - The sound bandwidth supports human voice only and so is sampled
- at 5012.5Hz Hz, 8bits, with zero level at value 80h.
-
- 2-Compression -
- A - The signal is converted to 4 bits, first subtracting DC value (80h) and
- using a log (base 2) conversion of the absolute value:
- in out
- 0 -> 0
- 0. .1 -> 1
- 2. .3 -> 2
- 4. .7 -> 3
- 8. .15 -> 4
- 16. .31 -> 5
- 32. .63 -> 6
- 64. .127 -> 7
- Now the signal is 4 bits with zero level at 0 (-16 to 15).
-
- B - The samples are packed 2 samples per byte, high nibble corresponding
- to first sample and the low nibble to next one
-
- EX:
- t = 0 0000hhhh <-- 4 bit sample
- 1 0000LLLL
-
- pack -> hhhhLLLL
-
- C - Run lenght encoded, using FFh as flag character.
-
- EX:
- 00 32 84 84 84 84 84 84 34 35 FF 54 54 FE FE FE FE FE FE
-
- is converted to:
- 00 32 FF 05 84 34 35 FF 01 FF 54 54 FF 06 FE
-
- 3-Coding - The signal is coded using 7 bits, from 30h to AFh.
-
- EX:
- 0 - AAAAaaaa - > 0 - 0AAAAaaa + 30h
- 1 - BBBBbbbb 1 - 0BBBBbbb + 30h
- 2 - CCCCcccc 2 - 0CCCCccc + 30h
- 3 - DDDDdddd 3 - 0DDDDddd + 30h
- 4 - EEEEeeee 4 - 0EEEEeee + 30h
- 5 - FFFFffff 5 - 0FFFFfff + 30h
- 6 - GGGGgggg 6 - 0GGGGggg + 30h
- 7 - 0abcdefg + 30h
-
- 4-Saving - The result is appended to the end of message at 64 bytes per line,
- with a header:
-
- "[TALK]" - 6 bytes - Identify a talkline
- 1Bh,"[8m" - 4 bytes - ANSI command to disable output, to avoid trash on
- mail readers/terminal emulators without sound capabilities.
- "A" - 1 byte - This version. Letters A to H are reserved.
- "00000" - 5 bytes - The size of the sound in bytes, after coding and
- without line feeds (E3h).
- E3h - 1 byte - The character used as LF by the QWK file format.
-
- .. follow first 64 bytes,E3h, and so on...
-
- =========================================================================
-
- As example, the routines, used to compress and expand the voice signal.
-
- //-----------------------------------------------------------------------
- UINT WaveCompress (LPSTR Pk, LPSTR Wav, UINT nS)
- //
- // Wav - intput signal
- // Pk - output signal
- // nS - number of data points
- //
- {
- register UINT k, T;
- char M;
- UINT Ncomp, nS;
-
- Log2(Wav, nS); ;4 bit convert
- Ncomp = nS >> 1;
- // pack data
- _asm {
- LES SI,Wav ;ES:SI -> Wav
- MOV DI,SI
- MOV CX,Ncomp
- JCXZ DONE
- L1: MOV AX,ES:[SI]
- SHL AL,4 ;shift to HI nibble
- AND AX,0FF0h ;mask
- OR AL,AH ;merge
- STOSB ;save
- ADD SI,2
- LOOP L1
- DONE:
- }
- //
- nS = 0;
- Wav[Ncomp] = (char)(Wav[Ncomp-1]+1); //make last different
- for(k=0; k<Ncomp; k++) //run lenght encode
- { T = 1;
- M = Wav[k];
- while (M == Wav[k+T]) //iqual next?
- { if(T == 253) break;
- else T = T + 1; //yes, bump T
- }
- if(T > 2 || M == '\xFF')
- { Wav[nS++] = 0xFF; //mark
- Wav[nS++] =(char)T; //total
- k = k + T - 1; //next
- }
- Wav[nS++] = M; //save data
- }
- Ncomp = Pack(Pk, Wav, nS); //7 bits convert
- return Ncomp;
- }
- //-----------------------------------------------------------------
- LONG WaveExpand (LPSTR Wav, LPSTR Pk, UINT nS)
- //
- // Pk - input signal
- // Wav - output signal
- // nS - number of data points
- //
- {
- register UINT T, k;
- UINT Cnt;
- LONG nExp, Pt;
-
- //
- nSamp = Unpack(Pk, Pk, nSamp); // 8 bits convert
- nExp = 0; // run lenght decode
- for(Pt=0; (UINT)Pt < nSamp; Pt++)
- { if(Pk[Pt] == (char) 0xFF )
- { Cnt = (BYTE) Pk[++Pt];
- T = (char)Pk[++Pt];
- for(k = 0; k < Cnt; k++) Wav[nExp++] = (char)T;
- }
- else
- { Wav[nExp++] = Pk[Pt]; }
- }
- Cnt =(UINT)nExp; //unpack
- _asm {
- LES DI, Wav
- MOV BX,Cnt
- OR BX,BX
- JZ DONE
- MOV SI,DI
- ADD SI,BX ;end of data
- ADD BX,BX ;end of unpacked data
- L1: MOV AL,ES:[SI]
- MOV AH,AL ;copy
- SHR AL,4 ;do inverse operation
- AND AX,0F0Fh ;mask
- MOV ES:[DI+BX],AX ;save
- DEC SI
- SUB BX,2
- JAE L1 ;for all data points
- DONE:
- }
- //
- nExp = nExp + nExp;
- Exp2(Wave, nExp); ;8 bit convert
- return nExp;
- }
- //=======================================================================
-
- Assebly routines to convert to and from 7 bits.
-
- ;-------------------------------------------------------------------------
- ; UINT = Pack (LPSTR, LPSTR, UINT);
- ;
- _Pack PROC FAR
- PUSH BP
- MOV BP,SP
- PUSHF
- CLD ;up
- PUSH DS
- PUSH SI
- PUSH DI
- XOR AX,AX ;zero return value
- MOV CX,[BP+14] ;size (up to 64k)
- JCXZ PACK9
- LES DI,[BP+6];
- LDS SI,[BP+10]; ;DS:SI -> string
- XOR BX,BX ;byte count
- ADD CX,SI ;offset end of input string
- PUSH DI ;save it
- ;
- PACK1: MOV DX,BX ;insert a 0E3h each 64 bytes
- AND DX,3FH ;test
- JNZ @F
- MOV AL,0E3h ;LF (on QWK...)
- STOSB ;insert
- @@: CMP SI,CX ;end of processing?
- JAE PACK2
- LODSW ;-- 1 & 2
- SHR AL,1 ;-> 7, bit 0 to CY
- RCL DH,1 ;CY to bit 0 on DH
- SHR AH,1 ;repeat to next byte
- RCL DH,1
- ADD AX,3030h ;translate to 30-A0h
- STOSW ;ok, save it
- LODSW
- SHR AL,1 ;repeat for bytes 3 & 4
- RCL DH,1
- SHR AH,1
- RCL DH,1
- ADD AX,3030h
- STOSW
- LODSW
- SHR AL,1 ;and 5 & 6
- RCL DH,1
- SHR AH,1
- RCL DH,1
- ADD AX,3030h
- STOSW
- LODSB
- SHR AL,1 ;the last one...
- RCL DH,1 ;
- MOV AH,DH ;save DH (7 saved bits)
- ADD AX,3030h ;
- STOSW ;
- ADD BX,8 ;total
- JMP PACK1
- PACK2: MOV AX,DI ;new position
- POP DI ;initial position
- SUB AX,DI ;return total processed bytes
- PACK9: XOR DX,DX ;AX:DX
- POP DI
- POP SI
- POP DS
- POPF
- MOV SP,BP
- POP BP
- RET
- _Pack ENDP
- ;-------------------------------------------------------------
- ; UINT = Unpack (LPSTR, LPSTR, UINT);
- ;
- _Unpack PROC FAR
- PUSH BP
- MOV BP,SP
- PUSHF
- PUSH DS
- PUSH SI
- PUSH DI
- CLD ;up
- XOR AX,AX
- MOV CX,[BP+14] ;size
- JCXZ UNPCK9
- LES DI,[BP+6]; ;ES:DI -> string
- LDS SI,[BP+10]; ;DS:SI -> string
- PUSH DI
- ;
- ;UNPCK0: LODSB
- ; CMP AL,30H ;if out of range (30h -> AFh)
- ; JB @F ;do not copy
- ; CMP AL,0B0H
- ; JA @F
- ; STOSB
- ;@@: LOOP UNPCK0
- ;
- UNPCK0: LODSB ;-- pcbord/qmail file corruption fix
- CMP AL,30H
- JAE @F
- CMP AL,'#' ;<<<
- JNE UNPK2
- MOV AL,'@' ;<<<
- @@: CMP AL,0B0H
- JA UNPK2
- STOSB
- UNPK2: LOOP UNPCK0
- ; ;------------
- MOV AX,DI
- POP DI
- SUB AX,DI ;total "clean" bytes
- LDS SI,[BP+6]
- LES DI,[BP+6] ;works only on destination
- ADD AX,7
- SHR AX,3 ;number of loops
- MOV CX,AX
- MOV BX,7
- MUL BX ;number of bytes
- MOV BX,AX ;save on BX
- UNPCK1: MOV DH,[SI+7] ;get saved bit
- SUB DH,30h ;convert to 0 - 7Fh
- RCL DH,1
- LODSW
- SUB AX,3030h ;convert data too
- RCL DH,1 ;bit -> CY
- RCL AL,1 ;insert on byte
- RCL DH,1 ;next byte
- RCL AH,1
- STOSW ;save
- LODSW
- SUB AX,3030h ;next 2 bytes
- RCL DH,1
- RCL AL,1
- RCL DH,1
- RCL AH,1
- STOSW
- LODSW
- SUB AX,3030h ;bytes 5 & 6
- RCL DH,1
- RCL AL,1
- RCL DH,1
- RCL AH,1
- STOSW
- LODSW
- SUB AL,30h ;the last...
- RCL DH,1
- RCL AL,1
- STOSB
- LOOP UNPCK1 ;repeat all
- MOV AX,BX
- UNPCK9: XOR DX,DX ;return total processed.
- POP DI
- POP SI
- POP DS
- POPF
- MOV SP,BP
- POP BP
- RET
- _Unpack ENDP
- ;---------------------------------------------------------------------
- ; Assembly routines to convert from 8 to 4 bits and from 4 to 8
- ;---------------------------------------------------------------------
- ; Log2 (LPSTR, UINT);
- ;
- _Log2 PROC FAR
- PUSH BP
- MOV BP,SP
- PUSHF
- PUSH ES
- PUSH DI
- CLD
- MOV BX,[BP+10] ;size to CX
- OR BX,BX
- JZ LOGC9
- LES DI,[BP+6]; ;ES:DI -> in/out - in place conversion
- LOGC1: MOV AL,ES:[DI]
- XOR CH,CH ;zero
- MOV DL,CH ;
- sub al,80h ;remove DC value (-128..127)
- OR AL,AL
- JNS @F ;if positive, go
- NEG AL ;signal change
- MOV DL,8 ;signal bit
- @@: AND AL,7FH
- SHL AL,1
- MOV CL,7
- @@: SHL AL,1
- JC @F
- LOOP @B
- @@: OR CL,DL ;insert signal
- MOV AL,CL
- ;
- STOSB ;save
- DEC BX ;end test
- JNZ LOGC1 ;no, more...
- LOGC9: POP DI
- POP ES
- POPF
- MOV SP,BP
- POP BP
- RET
- _Log2 ENDP
- ;-------------------------------------------------------------------
- ; Exp2 (LPSTR, UINT);
- ;
- _LogExp PROC FAR
- PUSH BP
- MOV BP,SP
- PUSHF
- PUSH ES
- PUSH DI
- CLD ;up
- XOR AX,AX
- MOV BX,[BP+10] ;size
- OR BX,BX
- JZ LOGE9
- LES DI,[BP+6]; ;ES:DI -> in/out
- XOR CH,CH
- LOGE1: MOV AL,ES:[DI]
- XOR AH,AH
- ;
- MOV CL,AL ;copy
- AND CL,7 ;signal mask
- STC
- RCL AH,CL ;exp
- TEST AL,8
- JZ @F ;if positive
- NEG AH
- @@: ADD AH,80H ;recover offset
- MOV AL,AH
- STOSB ;save
- DEC BX
- JNZ LOGE1 ;loop
- LOGE9: POP DI
- POP ES
- POPF
- MOV SP,BP
- POP BP
- RET
- _Exp2 ENDP
- ;========================================================================
-
- OBS: The music appended to the end of messages is a .MID file only coded
- into 7 bits. The file header is the same, only the identifier "TALK"
- change to "MIDI".
-
- ==========================================================================
- Carlos Pires, Rio, March 1993.
- ==========================================================================
- NOTE: Unpack routine correction to avoid file corruption over some BBSs
- systems, the change of "@" by "#".
- June, 1993.
- ==========================================================================
-
-